package com.lagou.niancheng.rpc.server.spring;

import com.alibaba.fastjson.JSONObject;
import com.lagou.niancheng.rpc.common.SimpleRpcConstants;
import com.lagou.niancheng.rpc.common.converter.Converter;
import com.lagou.niancheng.rpc.common.entity.HostPortMetaData;
import com.lagou.niancheng.rpc.common.exceptions.SimpleRpcException;
import com.lagou.niancheng.rpc.common.utils.HostUtil;
import com.lagou.niancheng.rpc.server.SimpleRpcConfig;
import com.lagou.niancheng.rpc.server.zookeeper.ZookeeperRegistryConfig;
import com.lagou.niancheng.rpc.server.zookeeper.ZookeeperRpcMethodRegistry;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * com.lagou.niancheng.rpc.server.spring.ZookeeperServiceProviderFactoryRegistrar
 *
 * @author 大犬
 * @date 2020/5/22
 */
public class ZookeeperServiceProviderFactoryRegistrar extends ServiceProviderFactoryRegistrar {

    private Logger logger = LoggerFactory.getLogger(ZookeeperServiceProviderFactoryRegistrar.class);

    @Override
    @SuppressWarnings("unchecked")
    protected SimpleRpcConfig buildConfig(AnnotationMetadata importingClassMetadata) {
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableSimpleRpcWithZookeeper.class.getName());
        if (annotationAttributes == null) {
            return new SimpleRpcConfig();
        }
        // 获取注解参数
        int port = (int) annotationAttributes.get("port");
        int workerThreadPoolSize = (int) annotationAttributes.get("workerThreadPoolSize");
        int masterThreadPoolSize = (int) annotationAttributes.get("masterThreadPoolSize");
        String zooServerAddress = (String) annotationAttributes.get("zooServerAddress");
        String serverName = (String) annotationAttributes.get("serverName");
        String namespace = (String) annotationAttributes.get("namespace");
        String hostIp = HostUtil.getHostIp().getHostName();

        // 如果服务名为空，则使用hostIp:port作为服务名节点
        if (StringUtils.isEmpty(serverName)) {
            serverName = hostIp + ":" + port;
        }
        // 实例化转换器
        Class<? extends Converter> converterClass = (Class<? extends Converter>) annotationAttributes.get("converterClass");
        Converter converter;
        try {
            converter = converterClass.newInstance();
        } catch (Exception e) {
            throw new SimpleRpcException("instant converter failed", e);
        }

        // 构建zookeeper方法注册中心
        HostPortMetaData hostPortMetaData = new HostPortMetaData().setHost(hostIp).setPort(port);
        ZookeeperRpcMethodRegistry zookeeperRpcMethodRegistry = buildZookeeperRpcMethodRegistry(zooServerAddress, hostPortMetaData, namespace, serverName);

        // 返回结果
        SimpleRpcConfig simpleRpcConfig = new SimpleRpcConfig();
        simpleRpcConfig.setPort(port);
        simpleRpcConfig.setMasterThreadPoolSize(masterThreadPoolSize);
        simpleRpcConfig.setWorkerThreadPoolSize(workerThreadPoolSize);
        simpleRpcConfig.setConverter(converter);
        simpleRpcConfig.setSimpleRpcMethodRegistry(zookeeperRpcMethodRegistry);
        return simpleRpcConfig;
    }

    private ZookeeperRpcMethodRegistry buildZookeeperRpcMethodRegistry(String zooServerAddress, HostPortMetaData hostPortMetaData, String namespace, String serverName) {
        ZookeeperRegistryConfig zookeeperRegistryConfig = new ZookeeperRegistryConfig();
        zookeeperRegistryConfig.setZooServerAddress(zooServerAddress);
        zookeeperRegistryConfig.setHostPortMetaData(hostPortMetaData);
        zookeeperRegistryConfig.setNamespace(namespace);
        zookeeperRegistryConfig.setServerName(serverName);
        return new ZookeeperRpcMethodRegistry(zookeeperRegistryConfig);
    }
}
